#include<sys/syscall.h>
#include<sys/ioctl.h>
#include<unistd.h>
#include<stdio.h>

#ifndef _HAS_OPENPT
int posix_openpt(int flags)
{
    return openclass("ptm",flags);
}
#endif 

#ifndef _HAS_PTSNAME
char *ptsname(int fd)
{
    uint32_t i_slave;
    static char pts_name[16];

    if(ioctl(fd,TTYIO_GETPTNUM,&i_slave)<0)
        return NULL;

    //dprintf("ptsname: ioctl get num %d\n",i_slave);
    
    pts_name[0]=0;
    snprintf(pts_name,sizeof(pts_name),"/dev/pts%d",i_slave);
    return pts_name;
}
#endif 

#ifndef _HAS_GRANTPT
int grantpt(int fd_master)
{
    char *pts_name;
    pts_name=ptsname(fd_master);
    pts_name++;
    return 0;
}
#endif 


#ifndef _HAS_UNLOCKPT
int unlockpt(int fd_master)
{
    uint8_t i_lock=0;
    return ioctl(fd_master,TTYIO_SETPTLOCK,&i_lock);
}
#endif 

int openpty(int *amaster,int *aslave,char *name)
{
    const char *slave;
    int mfd=-1,sfd=-1;
    *amaster=*aslave=-1;
    mfd=posix_openpt(O_RDWR|O_NOCTTY);
    if(mfd<0)
        goto err;
    if(grantpt(mfd)==-1||unlockpt(mfd)==-1)
        goto err;
    if((slave=ptsname(mfd))==NULL)
        goto err;
    if((sfd=open(slave,O_RDONLY|O_NOCTTY))==-1)
        goto err;

    if(amaster)
        *amaster=mfd;
    if(aslave)
        *aslave=sfd;
    return 0;

    err:
        return -1;
}

int ptym_open(char *pts_name,int namelen)
{
    char *name;
    int fdm=0;

    fdm=posix_openpt(O_RDWR|O_NOCTTY);
    if(fdm<0)
        return -1;
    
    if(grantpt(fdm)<0)
    {
        close(fdm);
        return -1;
    }

    if(unlockpt(fdm)<0)
    {
        close(fdm);
        return -1;
    }

    if((name=ptsname(fdm))==NULL)
    {
        close(fdm);
        return -1;
    }

    strncpy(pts_name,name,namelen);

    pts_name[namelen-1]=0;
    return fdm;
}

int ptys_open(const char *name)
{
    int fds;
    if((fds=open(name,O_RDWR))<0)
        return -1;
    return fds;
}